perm filename A47.TEX[106,RWF] blob sn#807756 filedate 1985-11-15 generic text, type C, neo UTF8
COMMENT āŠ—   VALID 00002 PAGES
C REC  PAGE   DESCRIPTION
C00001 00001
C00002 00002	\magnification\magstephalf
C00028 ENDMK
CāŠ—;
\magnification\magstephalf
\input macro.tex
\def\today{\ifcase\month\or
  January\or February\or March\or April\or May\or June\or
  July\or August\or September\or October\or November\or December\fi
  \space\number\day, \number\year}
\baselineskip 14pt
\rm
\line{\sevenrm a47.tex[106,phy] \today\hfill}

\bigskip
\line{\bf Appendix.\hfill}

\bigskip
\line{\bf Interpreting Error Messages from a Pascal Compiler.\hfill}

If your program contains syntactic errors, the compiler will provide diagnostic
messages.  Some of these are self-explanatory, but others may be obscure.
The examples below show how to interpret the messages resulting from many common
errors, from the widely used Hedrick translator.

The following correct program (not in Standard Pascal)
reads the position of a rook on a chessboard, and
prints a picture of the chessboard showing where the rook can move.
The underlined sections are locations where
errors will be inserted to demonstrate error messages.

\bigskip
\line{CORRECT PROGRAM\hfill}

\medskip
{\obeylines\obeyspaces\let =\ \tt
\parindent0pt
\def\ut{\undertext}
 1  program Rook;
 2      var RookRow\undertext{,}
 3          RookCol,
 4          Row, Col : integer;
 5  begin  
 6      writeln ( tty, ' Rook on Chessboard ' ) ;
 7      writeln ( tty, ' ------------------ ' ) ;
 8      write ( tty, ' RookRow          = ' ) ;
 9      break ( tty ) ;
10      read ( tty , RookRow ) ;
11      write ( tty, ' RookColumn       = \undertext{'} ) ;
12      break ( tty ) ;
13      read ( tty , RookCol ) ;
14      while \ut{(}RookRow<1\ut{)} or \ut{(}RookRow>8\ut{)} or \ut{(}RookCol<1\ut{)} or \ut{(}RookCol>8\ut{)} \ut{do}
15          begin writeln ( tty, ' Invalid input -- Try again ' ) \undertext{;}
16          write ( tty, ' RookRow    = ' ) ;
17          break ( tty ) ;
18          read ( tty , RookRow ) ;
19          write ( tty, ' RookColumn = ' ) ;
20          break ( tty ) ;
21          read ( tty , RookCol ) ;
22          \ut{end;   (* while \ut{*})}
23      for Row \ut{:=} 1 to 8 do
24          begin
25          for Col:= 1 to 8 do
26              if Row = RookRow then
27                  if Col \ut{=} RookCol
28                      then write ( tty, ' R' )\ut{\ }
29                      else write ( tty , ' *' )
30              else if Col = RookCol
31                  then write ( tty, ' *' )
32                  else write ( tty, ' -' ) ;
33           writeln ( tty );
34           end
35  \ut{end.}

\bigskip
\line{\rm{NORMAL OUTPUT}\hfil}

\medskip
Stanford LOTS/Passgo 20 [ROOK  ] -- 1.. 
Runtime:   0: 0.252
[ROOK   execution]
 Rook on Chessboard 
 ------------------ 
 RookRow          = 4
 RookColumn       = 6
 - - - - - * - -
 - - - - - * - -
 - - - - - * - -
 * * * * * R * *
 - - - - - * - -
 - - - - - * - -
 - - - - - * - -
 - - - - - * - -
}

\medskip
Line 2: Omit the comma.   The resulting error messages follow.  The second line
copies a portion of the program where an error was found; the arrow is
under the place where the compiler discovered the error, which may be well beyond
where the error occurred.  Line 4 refers (``{\tt 1.$\uparrow$}'') 
to the first arrow, and says
that the symbol ``{\tt ROOKCOL}'' 
is illegal there; only a comma or a semicolon would
have been legal at the beginning of Line~3.
Because of the garbled declaration, the variable {\tt ROOKCOL} 
is undeclared; every occurrence of {\tt ROOKCOL}
results in an error message.  Frequently, many messages will result from one
error, and the first message may be the only useful one.

\vfill\eject

{\obeylines\obeyspaces\let =\ \tt
\parindent0pt

Stanford LOTS/Passgo 20 [ROOK  ] -- 1.. 
    3           RookCol,
P*  1**                $\uparrow$
1.$\uparrow$:  Illegal symbol 

   13       read ( tty , RookCol ) ;
P*  1**                        $\uparrow$
1.$\uparrow$:  Identifier not declared  


   14       while (RookRow < 1) or (RookRow > 8) or (RookCol < 1) or (RookCol
> 8) do
P*  1**                                                    $\uparrow$                $\uparrow$   
     
1.$\uparrow$:  Identifier not declared  
2.$\uparrow$:  Identifier not declared  

   21           read ( tty , RookCol ) ;
P*  1**                            $\uparrow$    
1.$\uparrow$:  Identifier not declared  

   27                   if Col = RookCol
P*  1**                                $\uparrow$
1.$\uparrow$:  Identifier not declared  

   30               else if Col = RookCol
P*  1**                                 $\uparrow$
1.$\uparrow$:  Identifier not declared  

?   7 Error(s) detected
}

\medskip
Line 11: Omit the closing quote.  The resulting error messages follow.  The first
message says that the quoted string contains a carriage return.  While this
helps locate the error, it does not accurately describe the error.  
When the closing quote is omitted, the right parenthesis is treated as part of the
quoted string; the result is a missing right parenthesis, as the second
error message explains.

\medskip
{\obeylines\obeyspaces\let =\ \tt
\parindent0pt
Stanford LOTS/Passgo 20 [ROOK  ] -- 1.. 

   11       write ( tty, ' RookColumn       =  ) ;
P*  1**                                          $\uparrow$
1.$\uparrow$:  String constant contains "<CR><LF>"
1.$\uparrow$:  ")" expected   

?   2 Error(s) detected
}

\medskip
Line 14: Omit all the parentheses.  Since Pascal requires parentheses when
relations are connected by {\tt AND} or {\tt OR}, 
the compiler misinterprets the expression as if it were 
{\tt while Rookrow<(1 or Rookrow)>(8 or} , etc.

\medskip
{\obeylines\obeyspaces\let =\ \tt
\parindent0pt
Stanford LOTS/Passgo 20 [ROOK  ] -- 1.. 

   14       while RookRow < 1 or RookRow > 8 or RookCol < 1 or RookCol > 8 do
P*  1**                                  $\uparrow$**  $\uparrow$          **            $\uparrow$**   
1.$\uparrow$:  Illegal symbol 
2.$\uparrow$:  Illegal type of operand(s)    
3.$\uparrow$:  Illegal symbol 

?   3 Error(s) detected
}

\medskip
Line 14: Change {\tt DO} to {\tt THEN}.  
The compiler treats this as two separate errors:
the inclusion of an unwanted {\tt THEN}, and the omission of {\tt DO}.

\medskip
{\obeylines\obeyspaces\let =\ \tt
\parindent0pt
Stanford LOTS/Passgo 20 [ROOK  ] -- 1.. 
   14       while (RookRow < 1) or (RookRow > 8) or (RookCol < 1) or (RookCol
> 8) then
P*  1**                                                                         
      $\uparrow$
1.$\uparrow$:  Illegal symbol 

   15           begin writeln ( tty, ' Invalid input -- Try again ' ) ;
P*  1**             $\uparrow$                                                  
1.$\uparrow$:  "DO" expected  

?   2 Error(s) detected
}

\medskip
Line 15: Omission of the semicolon. The omission is detected at the beginning
of the next statement.  The compiler ignores a subsequent part of the program,
shown by underlining with asterisks, before starting to translate correctly again.

\medskip
{\obeylines\obeyspaces\let =\ \tt
\parindent0pt
Stanford LOTS/Passgo 20 [ROOK  ] -- 1.. 
   16           write ( tty, ' RookRow    = ' ) ;
P*  1**             $\uparrow$**************************  
1.$\uparrow$:  Statement must end with ";","END","ELSE"or"UNTIL" 

?   1 Error(s) detected
}

\medskip
Line 22: Omit the entire line.  In addition to the valid error message, a
spurious one is generated.  Perhaps the compiler repaired the first error by
inserting only a semicolon; the need for another {\tt END} is then discovered at
the end of the program.

\medskip
{\obeylines\obeyspaces\let =\ \tt
\parindent0pt
Stanford LOTS/Passgo 20 [ROOK  ] -- 1.. 
   34   end.
P*  1**    $\uparrow$
1.$\uparrow$:  Statement must end with ";","END","ELSE"or"UNTIL" 
?  Unexpected end of file
}

\medskip
Line 22: Omit the second asterisk.  As a result, the rest of the program is
treated as a comment, including the ``{\tt END}.''  which normally terminates a
program.  The resulting error message is one of the most cryptic, since it
is located nowhere near the actual error, and does not describe the error.
If all else fails, when the {\tt BEGIN}s and {\tt END}s 
unexplainably don't seem to match
in a program, check that the comments all terminate properly.

\medskip
{\obeylines\obeyspaces\let =\ \tt
\parindent0pt
Stanford LOTS/Passgo 20 [ROOK  ] -- 1.. ?  Unexpected end of file
?  Unterminated Comment at 1/22
}

\medskip
Line 23: Insert a space between ``{\tt :}'' and ``{\tt =}''.  
Pascal prohibits spaces
within ``{\tt :=}'', ``{\tt <>}'', ``{\tt <=}'', and ``{\tt >=}''.

\medskip
{\obeylines\obeyspaces\let =\ \tt
\parindent0pt
Stanford LOTS/Passgo 20 [ROOK  ] -- 1.. 
   23       for Row: = 1 to 8 do
P*  1**            $\uparrow$****
1.$\uparrow$:  ":=" expected  

?   1 Error(s) detected
}

\medskip
Line 23: Omit the colon.  The distinction between ``{\tt =}'' and ``{\tt :=}'' 
must be
maintained in Pascal.

\medskip
{\obeylines\obeyspaces\let =\ \tt
\parindent0pt
Stanford LOTS/Passgo 20 [ROOK  ] -- 1.. 
   23       for Row = 1 to 8 do
P*  1**             $\uparrow$**        
1.$\uparrow$:  ":=" expected  

?   1 Error(s) detected
}

\medskip
Line 27: Replace ``{\tt =}'' by ``{\tt :=}''.

\medskip
{\obeylines\obeyspaces\let =\ \tt
\parindent0pt
Stanford LOTS/Passgo 20 [ROOK  ] -- 1.. 
   27                   if Col := RookCol
P*  1**                         $\uparrow$******* 
1.$\uparrow$:  Illegal symbol 

   28                       then write ( tty, ' R' )
P*  1**                        $\uparrow$                    
1.$\uparrow$:  Type of operand(s) must be boolean 

?   2 Error(s) detected
}

\medskip
Line 28: Insert a semicolon at the end of the line.  A semicolon before an
{\tt ELSE} terminates the conditional command prematurely, making an orphan of
the {\tt ELSE}.

\medskip
{\obeylines\obeyspaces\let =\ \tt
\parindent0pt
Stanford LOTS/Passgo 20 [ROOK  ] -- 1.. 
   29                       else write ( tty , ' *' )
P*  1**                        $\uparrow$******************** 
1.$\uparrow$:  Illegal symbol 
   30               else if Col = RookCol
P*  1** ****************                 

?   1 Error(s) detected
}

\medskip
Line 35: Omit.

\medskip
{\obeylines\obeyspaces\let =\ \tt
\parindent0pt
Stanford LOTS/Passgo 20 [ROOK  ] -- 1.. ? Unexpected end of file
}
 
\medskip
Ordinarily, a careful reading of the error messages will locate a syntactic error.
Occasionally, though, there are few clues.  In extreme cases, use the {\sl bisection
method\/}. (Since this entails radical surgery on the program, you should first
copy it and alter only the copy.) Remove or replace large parts of the 
program, such as procedure declarations and compound statements, and see if
the resulting program still gives rise to the same error message.  If so,
continue the amputations.  If not, the error is presumably in one of the
removed parts; put them back in, and remove parts of them, until the error
is localized to a few lines of the program.

\medskip
\line{\bf Example.\hfill}

{\obeylines\obeyspaces\let =\ \tt
        PROGRAM - - -
         $\vdots$
        PROCEDURE - - -
         $\vdots$
        PROCEDURE - - -
         $\vdots$
        BEGIN
            BEGIN
             $\vdots$
            END
        FOR - - - DO
            BEGIN
             $\vdots$
            READ(*)
             $\vdots$
            END
        END.
}

\medskip
This program gives rise to a single error message, 
``{\tt END OF PROGRAM NOT FOUND}''.
This usually results from a non-terminated comment, but the program contains no
comments.  First, remove the procedure declarations.  The error persists (along
with several new messages about the undeclared procedure names).  Next change
the long compound command following {\tt DO} to a simple one, 
perhaps {\tt WRITELN}.  Now
the error message goes away.  The trouble has been located in those lines.
If necessary, restore the compound statement (perhaps by returning to the
previous generation of the file) and delete the component statements one by one.
When the {\tt READ} 
line is deleted, the error message vanishes.  Upon inspection, we see
that {\tt READ(*)} was typed where {\tt READ(x)} was intended, the 
``{\tt (*}'' was taken as the
start of a comment, and the rest of the program was taken as part of that
comment.

The bisection method is also a heavy duty method for locating semantic errors
in a program free of syntactic errors.  If the results are wrong, make the
program print the values of all variables (called the {\sl state\/}) at a point about
halfway through the execution.  If they are correct, the problem lies in the
second half of the proram; if wrong, there is something wrong in the first half.
Bisect the offending part again.  If the problem has been traced to an iteration,
make it print the state after the first execution, and, if necessary, after the
second, and before the last execution.  Usually this will localize the error.
In general, by editing a program, you can make it give you enough information
to locate its errors, assuming that you understand what the program was supposed
to be doing.


\medskip
\parindent0pt
\copyright 1984 Robert W. Floyd

First draft March 28, 1984

\bye